import os
import logging
from rest_framework import viewsets
from rest_framework import mixins
from rest_framework.views import APIView
from rest_framework.parsers import (
    MultiPartParser,
    FormParser,
)
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework.filters import SearchFilter
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .models import file_upload
from .serializers import FileDetailSerializer
from libs.paginations import ListPagination
from .utils.oss_upload import FileUpload_To_OSS

CUSTOM_ERROR = logging.getLogger('apps.views')


class FileListViewSet(viewsets.GenericViewSet,
                      mixins.ListModelMixin,
                      mixins.DestroyModelMixin):
    # 获取上传的文件信息

    queryset = file_upload.objects.all()
    serializer_class = FileDetailSerializer
    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    pagination_class = ListPagination
    filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter)
    order_fields = ('id',)
    filter_fields = ('env', 'file_type', 'child_type')
    search_fields = ('name',)

    def destroy(self, request, *args, **kwargs):
        '''删除数据库文件记录并同时删除oss文件'''

        instance = self.get_object()
        self.perform_destroy(instance)
        start_oss_upload = FileUpload_To_OSS(env=instance.env, filename=instance.name, filetype=instance.file_type,
                                             childtype=instance.child_type)

        return Response(start_oss_upload.deleteOssFile())


class FileUploadApiView(APIView):
    '''文件上传接口 传参：{'env':str,'file_type':str}, env：上传文件到哪个环境使用，file_type：上传的文件类型'''

    parser_classes = (MultiPartParser, FormParser)
    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

    def file_md5_val(self, filepath, filename):
        '''计算文件的MD5值'''

        import hashlib
        md5 = hashlib.md5()
        file_dir = os.path.join(filepath, filename)
        with open(file_dir, 'rb') as f:
            file_byte = f.read()
        md5.update(file_byte)
        return md5.hexdigest()

    def post(self, request, format=None):
        env = request.data['env']
        file_type = request.data['file_type']
        child_type = request.data['file_type']
        if file_type == 'image':
            child_type = request.data['child_type']
        file_obj = request.data['file']
        # if file_obj is None:
        #     return Response({'msg':'not found file'})
        file_path = "./SourceFloder"

        if os.path.exists(file_path) is False:
            os.makedirs(file_path)

        # 开始执行上传任务
        try:
            with open(os.path.join(file_path, file_obj.name), 'wb') as f:
                for file in file_obj.chunks():
                    f.write(file)
        except IOError as e:
            CUSTOM_ERROR.error(f'{e.__class__.__name__}: {e}')
            return Response({'msg': f'{file_obj.name} upload failed'})

        # 通过验证文件的md5值判断文件是否已经存在
        file_data = file_upload.objects.filter(file_md5=self.file_md5_val(file_path, file_obj.name)).values().first()
        if file_data is not None:
            os.remove(os.path.join(file_path, file_obj.name))
            return Response({'msg': f'The file {file_obj.name}  already exists', 'url': file_data.get('file_url')})

        start_oss_upload = FileUpload_To_OSS(env=env, filename=file_obj.name, filetype=file_type, childtype=child_type)

        return Response(
            start_oss_upload.uploading(filepath=file_path, fileMD5=self.file_md5_val(file_path, file_obj.name)))
